package com.cd.university.service.impl;

import com.cd.university.common.RestResult;
import com.cd.university.common.UniversityConstants;
import com.cd.university.common.obs.ObsUtils;
import com.cd.university.common.task.LogFileUpLoadTask;
import com.cd.university.controller.form.LogTimeForm;
import com.cd.university.db.mapper.OperationLogMapper;
import com.cd.university.db.mapper.SystemLogMapper;
import com.cd.university.db.mapper.UserLoginLogMapper;
import com.cd.university.db.pojo.OperationLog;
import com.cd.university.db.pojo.SystemLog;
import com.cd.university.db.pojo.UserLoginLog;
import com.cd.university.service.LogService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @author 陈栋
 * @create 2021/11/7 20:27
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class LogServiceImpl implements LogService, InitializingBean {

    @Autowired
    private UserLoginLogMapper userLoginLogMapper;

    @Autowired
    private OperationLogMapper operationLogMapper;

    @Autowired
    private SystemLogMapper systemLogMapper;

    /**
     * 存放所有的日志Mapper类
     */
    private static HashMap<String, Object> logMapperMap = new HashMap<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        logMapperMap.put("userLoginLog",userLoginLogMapper);
        logMapperMap.put("operationLog",operationLogMapper);
        logMapperMap.put("systemLog",systemLogMapper);
    }

    @Autowired
    private ObsUtils obsUtils;

    public final static SimpleDateFormat dateFormat =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


    @Override
    public RestResult getUserLog(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<UserLoginLog> userLoginLogAll = userLoginLogMapper.getUserLoginLogAll();
        PageInfo pageInfo = new PageInfo(userLoginLogAll);
        pageInfo.setList(userLoginLogAll);
        return RestResult.success("获得数据如下")
                .put("data",pageInfo);
    }

    @Override
    public RestResult deleteUserLog(List<LogTimeForm> userLogList) {
        int count = 0;
        for (LogTimeForm logTimeForm : userLogList) {
            int row = userLoginLogMapper.deleteByPrimaryKey(logTimeForm.getLogTime());
            count+=row;
        }
        return RestResult.success("总共删除了" + count + "条数据");
    }

    @Override
    public RestResult getOperationLog(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<OperationLog> allOperationLog = operationLogMapper.getAllOperationLog();
        PageInfo pageInfo = new PageInfo(allOperationLog);
        pageInfo.setList(allOperationLog);

        return RestResult.success("获得数据如下")
                .put("data",pageInfo);
    }

    @Override
    public RestResult deleteOperationLog(List<LogTimeForm> operationLogList) {
        int count = 0;
        for (LogTimeForm logTimeForm : operationLogList) {
            int row = operationLogMapper.deleteByPrimaryKey(logTimeForm.getLogTime());
            count+=row;
        }
        return RestResult.success("总共删除了" + count + "条数据");
    }

    @Override
    public RestResult getSystemLog(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<SystemLog> systemLogs = systemLogMapper.searchAll();
        PageInfo pageInfo = new PageInfo(systemLogs);
        pageInfo.setList(systemLogs);
        return RestResult.success("系统日志的全部数据")
                .put("data",pageInfo);
    }

    @Override
    public RestResult deleteSystemLog(List<LogTimeForm> systemList) {
        int row = 0;
        for (LogTimeForm form : systemList) {
            deleteObsFile(form.getSystemLogId());
            row += systemLogMapper.deleteByPrimaryKey(form.getSystemLogId());
        }
        return RestResult.success("成功删除了： " + row + "条数据");
    }

    @Override
    public RestResult searchByTime(Integer pageNum, Integer pageSize, String startTime, String endTime, String type) {
        String methodName = "searchByTime";
        Date sTime = null;
        Date eTime = null;
        try {
            sTime = dateFormat.parse(startTime);
            eTime = dateFormat.parse(endTime);
        } catch (ParseException e) {
            e.printStackTrace();
            RestResult.failure("传入的时间出错，请重试");
        }
        return invokeMethod(pageNum,pageSize,type,methodName,sTime,eTime);
    }

    @Async
    public void deleteObsFile(Integer systemLogId) {
        // 查询数据库中的日志文件
        SystemLog systemLog = systemLogMapper.selectByPrimaryKey(systemLogId);

        if (systemLog==null) {
            throw new RuntimeException("系统日志不存在请检查");
        }
        // 删除日志文件
        obsUtils.deleteFile(systemLog.getSystemLogFileName(), UniversityConstants.SYSTEM_LOG_FILE_FOLDER);
        // TODO: 2021/11/8 删除本地文件
//        boolean deleteSystemLog = LogFileUpLoadTask.deleteSystemLog(systemLog.getSystemLogFileName());
//        if (deleteSystemLog) {
//            log.info("删除" + systemLog.getSystemLogFileName() + "文件成功");
//        }
    }

    private RestResult invokeMethod(Integer pageNum, Integer pageSize, String type, String methodName, Object... args) {
        Object logMapper = logMapperMap.get(type);
        Class<?> logMapperClass = logMapper.getClass();

        // 寻找方法的参数类型
        Class<?>[] parameterTypes = null;
        Method[] methods = logMapperClass.getDeclaredMethods();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                parameterTypes = method.getParameterTypes();
                break;
            }
        }

        Method method = null;
        try {
            // 如果是无参数的方法
            if (parameterTypes.length==0) {
                method = logMapperClass.getDeclaredMethod(methodName);
            }
            // 否则,调用有参的
            else {
                method = logMapperClass.getDeclaredMethod(methodName,parameterTypes);
            }
            PageHelper.startPage(pageNum,pageSize);
            List<Object> invoke = (List<Object>) method.invoke(logMapper, args);
            PageInfo pageInfo = new PageInfo(invoke);
            pageInfo.setList(invoke);

            return RestResult.success("按照时间搜索结果如下")
                    .put("data",pageInfo);

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            log.error(logMapperClass.getSimpleName() + "失败,没有找到类");
            return RestResult.failure(logMapperClass.getSimpleName() + "失败,没有找到类");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            log.error(logMapperClass.getSimpleName() + "方法执行失败，无法访问当前方法");
            return RestResult.failure(logMapperClass.getSimpleName() + "方法执行失败，无法访问当前方法");
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            log.error(logMapperClass.getSimpleName() + "方法执行失败");
            return RestResult.failure(logMapperClass.getSimpleName() + "方法执行失败");
        }

    }

}

